package yunjiao.javatutorials.guava.concurrent.timed;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 *  性能测试框架
 *
 * @author yangyunjiao
 */
public class ConcurrentPerformanceTest {
    private final TimedCondition testCondition;
    private final Lock lock;
    private int readyThreads = 0;
    private final int totalThreads;

    public ConcurrentPerformanceTest(int totalThreads) {
        this.totalThreads = totalThreads;
        this.lock = new ReentrantLock();
        this.testCondition = new TimedCondition(lock.newCondition());
    }

    public void runTest() throws InterruptedException {
        List<Thread> threads = new ArrayList<>();

        // 创建测试线程
        for (int i = 0; i < totalThreads; i++) {
            Thread thread = new TestWorker(i, testCondition, lock);
            threads.add(thread);
        }

        // 启动所有线程
        threads.forEach(Thread::start);

        // 等待所有线程准备就绪
        lock.lock();
        try {
            while (readyThreads < totalThreads) {
                testCondition.await(5, TimeUnit.SECONDS);
            }
            System.out.println("所有线程准备就绪，开始测试...");

            // 通知所有线程开始执行
            testCondition.signalAll();
        } finally {
            lock.unlock();
        }

        // 等待测试完成
        for (Thread thread : threads) {
            thread.join();
        }

        // 打印性能统计
        testCondition.printStatistics();
    }

    private class TestWorker extends Thread {
        private final int workerId;
        private final TimedCondition condition;
        private final Lock workerLock;

        public TestWorker(int workerId, TimedCondition condition, Lock lock) {
            super("TestWorker-" + workerId);
            this.workerId = workerId;
            this.condition = condition;
            this.workerLock = lock;
        }

        @Override
        public void run() {
            workerLock.lock();
            try {
                // 报告准备就绪
                readyThreads++;
                System.out.println("Worker " + workerId + " 准备就绪");
                condition.signal();

                // 等待开始信号
                condition.await();

                // 执行测试任务
                System.out.println("Worker " + workerId + " 开始执行");
                performWork();

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                workerLock.unlock();
            }
        }

        private void performWork() {
            // 模拟工作负载
            try {
                Thread.sleep(1000 + (int)(Math.random() * 1000));
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            System.out.println("Worker " + workerId + " 完成工作");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ConcurrentPerformanceTest test = new ConcurrentPerformanceTest(5);
        test.runTest();
    }
}
